/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once
#include <baja/common.hpp>

namespace journal { namespace app {

namespace b = baja;

enum class key
{
    none = 0,
    help,
    saveThumbnail,
    dumpNotebookModel,
    zoomLevelDown,
    zoomLevelUp,
    addNewPage,
    cameraModeOff,
    restoreCamera,
    cameraModeFocus,
    cameraModeRotate,
    cameraModeMove,
    cameraModeZoom,
    cameraModeRotateLight,
    debugConsole,
    varConsole,
    clearDebugConsole,
    redrawPage,
    smooth,
    smoothVectorized,
    showDisclaimer,
    togglePerf,
    testInk1,
    testAnimation1,
    testAnimation2,
    curlPage,
    resetPageCurl,
    toggleMemoryMonitors,
    toggleStackExpansion,
    resetPerformanceMonitors,
    resetSettings,
    saveImage,
    copy,
    paste,
    undo,
    redo,
    credits,
    runTests
};

struct key_registry : public b::ibase
{
    void bind(const key k, const b::int32 c, const b::wchar* desc)
    {
        auto it = _bindings.find(k);

        if (it != _bindings.end()) { BAJA_THROW(std::logic_error("key binding already set!")); }

        _bindings[k] = key_binding(k, c, desc);
    }

    static bool check(const key k, const b::int32 c) { return _singleton->checkInternal(k, c); }
    static void initialize();
    static void printHelp() { return _singleton->printHelpInternal(); }

private:
    bool checkInternal(const key k, const b::int32 c);
    void printHelpInternal();

    static std::shared_ptr<key_registry> _singleton;

    struct key_binding
    {
        key k;
        b::int32 c;
        const b::wchar* desc;

        key_binding() : k(key::none), c(' '), desc(L"") {}
        key_binding(const key k_, const b::int32 c_, const b::wchar* desc_) : k(k_), c(c_), desc(desc_) {}
        key_binding(const key_binding& other) : k(other.k), c(other.c), desc(other.desc) {}
        key_binding operator=(const key_binding& other)
        {
            this->k = other.k;
            this->c = other.c;
            this->desc = other.desc;
            return *this;
        }
    };

    std::map<const key, key_binding> _bindings;
};

}} // namespace journal::app